<template>
	<div class="statusbarItem" ref="rootRef">
		<!-- 提示 -->
		<template v-if="!props.notTooltip">
			<div
				class="tooltip"
				ref="tooltipDom"
				:class="{ unselect: props.tooltipUnselect }"
				v-show="state.tooltipShow">
				<span v-if="props.tooltip">{{ props.tooltip }}</span>
				<template v-else>
					<slot name="tooltip"></slot>
				</template>
				<!-- 指针 -->
				<div class="pointer"></div>
			</div>
		</template>
		<!-- 内容 -->
		<div
			class="content"
			:class="{ center: props.contentCenter, active: state.hover }"
			ref="contentDom"
			@mouseenter="onMouseenter"
			@mouseleave="onMouseleave"
			@click="emit('click')">
			<slot></slot>
		</div>
		<!-- 三角 -->
		<div class="beak" v-show="props.showBeak"></div>
	</div>
</template>

<script setup lang="ts">
import { reactive, ref, watch, nextTick } from 'vue';

const emit = defineEmits(['click']);
const slots = defineSlots();
const props = defineProps({
	// tooltip 显示延迟时间
	tooltipShowAfter: {
		type: Number,
		default: 0,
	},
	// tooltip 内容
	tooltip: String,
	// tooltip 是否不能选择
	tooltipUnselect: {
		type: Boolean,
		default: false,
	},
	// 是否不显示 tooltip
	notTooltip: {
		type: Boolean,
		default: false,
	},
	// 内容是否居中
	contentCenter: {
		type: Boolean,
		default: true,
	},
	// 是否显示三角
	showBeak: {
		type: Boolean,
		default: false,
	},
});

const state = reactive({
	hover: false,
	tooltipShow: false,
});

const contentDom = ref<HTMLDivElement>();
const tooltipDom = ref<HTMLDivElement>();

let tempr: NodeJS.Timeout;

// 鼠标移入
function onMouseenter() {
	state.hover = true;

	if (slots.tooltip || props.tooltip) {
		if (props.tooltipShowAfter > 0) {
			tempr = setTimeout(() => {
				state.tooltipShow = true;
				setTooltipPosition();
			}, props.tooltipShowAfter);
		} else {
			state.tooltipShow = true;
			setTooltipPosition();
		}
	}
}
// 鼠标移出
function onMouseleave() {
	state.hover = false;

	if (slots.tooltip || props.tooltip) {
		if (props.tooltipShowAfter > 0) {
			clearTimeout(tempr);
			state.tooltipShow = false;
		} else {
			state.tooltipShow = false;
		}
	}
}

/**
 * 获取元素的 x 轴
 */
function getLeft(e: HTMLElement) {
	let offset = e.offsetLeft;
	if (e.offsetParent) {
		offset += getLeft(e.offsetParent as HTMLElement);
	}
	return offset;
}

/**
 * 设置提示位置
 * @param s 是否异步
 */
function setTooltipPosition(s?: boolean) {
	function fn() {
		if (!tooltipDom.value || !contentDom.value) return;

		const margin = 5; // 两边的边距
		const windowWidth = document.body.offsetWidth;
		const tooltipDomWidth = tooltipDom.value.offsetWidth;
		const contentDomInfo = {
			x: getLeft(contentDom.value),
			width: contentDom.value.offsetWidth,
		};

		let left = contentDomInfo.width / 2 - tooltipDomWidth / 2;
		let pointerLeft = tooltipDomWidth / 2 - 2.5;

		if (contentDomInfo.x + left < margin) {
			const value = Math.abs(contentDomInfo.x + left - margin);

			left += value;
			pointerLeft -= value;
		}

		if (contentDomInfo.x + left + tooltipDomWidth > windowWidth - margin) {
			const value = contentDomInfo.x + left + tooltipDomWidth - (windowWidth - margin);

			left -= value;
			pointerLeft += value;
		}

		tooltipDom.value.style.setProperty('--tooltip-left', left + 'px');
		tooltipDom.value.style.setProperty('--pointer-left', pointerLeft + 'px');
	}

	if (s) {
		fn();
	} else {
		nextTick(() => {
			fn();
		});
	}
}

// 实时更新位置
watch(
	() => props.tooltip,
	() => {
		if (state.tooltipShow) {
			setTooltipPosition();
		}
	}
);
</script>

<style scoped lang="scss">
// 设置暗色/亮色模式下的颜色
html:not(.dark) .statusbarItem {
	--fill-color-my: #f3f3f3;
	--border-color-my: #c8c8c8;
	.tooltip {
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.16);
		color: #616161;
	}
}
html.dark .statusbarItem {
	--fill-color-my: #262727;
	--border-color-my: #4c4d4f;
}
// 设置 tooltip 指针在暗色/亮色模式切换时的过度样式
html.SCSA .statusbarItem .pointer::after {
	transition: var(--SCST);
}
.statusbarItem {
	position: relative;
	display: inline-block;
	.tooltip {
		position: absolute;
		bottom: calc(100% + 4px);
		left: var(--tooltip-left);
		background-color: var(--fill-color-my);
		border: 1px solid var(--border-color-my);
		padding: 3px 10px;
		font-size: 13px;
		z-index: 99;
		white-space: nowrap;
		user-select: none;
		border-radius: 3px;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.36);
		.pointer {
			position: absolute;
			bottom: 2px;
			left: var(--pointer-left);
			&::after {
				content: '';
				position: absolute;
				width: 5px;
				height: 5px;
				transform: rotate(45deg);
				background-color: var(--fill-color-my);
				border-right: 1px solid var(--border-color-my);
				border-bottom: 1px solid var(--border-color-my);
			}
		}
		&.unselect {
			user-select: none;
		}
	}
	.content {
		padding: 0 6px;
		height: 100%;
		position: relative;
		overflow: hidden;
		cursor: pointer;
		&:hover {
			background-color: var(--item-mouse-hover-bg-color);
		}
		&.center {
			display: flex;
			align-items: center;
		}
	}
	.beak {
		position: absolute;
		left: calc(50% - 5px);
		top: -5px;
		width: 10px;
		height: 5px;
		&::after {
			content: '';
			position: absolute;
			border-bottom-width: 5px;
			border-bottom-style: solid;
			border-left: 5px solid transparent;
			border-right: 5px solid transparent;
			color: var(--statusbar-bg-color);
		}
	}
}
</style>
